﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace PPSkin
{
    public class PPDataGridViewButtonCell : DataGridViewButtonCell
    {
        private Color regularBaseColor = Color.White;
        private Color regularLineColor = Color.LightGray;
        private Color regularTextColor = Color.Black;

        private Color mouseInBaseColor = Color.LightGray;
        private Color mouseInLineColor = Color.Silver;
        private Color mouseInTextColor = Color.Black;

        private Color mouseDownBaseColor = Color.DimGray;
        private Color mouseDownLineColor = Color.Silver;
        private Color mouseDownTextColor = Color.Black;

        private int radius = 5;
        private int lineWidth = 1;
        private int xoffset = 0;
        private int yoffset = 0;
        private int xoffsetIco = 0;
        private int yoffsetIco = 0;

        private Image icoRegular = null;
        private Image icoIn = null;
        private Image icoDown = null;
        private Size icoSize = new Size(15, 15);

        [Description("圆角半径"), Category("自定义")]
        public int Radius
        {
            get { return radius; }
            set
            {
                radius = value;
            }
        }

        [Description("边框宽度,只能是奇数"), Category("自定义")]
        public int LineWidth
        {
            get { return lineWidth; }
            set
            {
                lineWidth = value;// % 2 == 0 ? value + 1 : value;
            }
        }

        [Description("文本x方向偏移量，为正向右，为负向左"), Category("自定义")]
        public int Xoffset
        {
            get { return xoffset; }
            set
            {
                xoffset = value;
            }
        }

        [Description("文本y方向偏移量，为正向下，为负向上"), Category("自定义")]
        public int Yoffset
        {
            get { return yoffset; }
            set
            {
                yoffset = value;
            }
        }

        [Description("正常背景色"), Category("自定义")]
        public Color RegularBaseColor
        {
            get { return regularBaseColor; }
            set
            {
                regularBaseColor = value;
            }
        }

        [Description("正常边框色"), Category("自定义")]
        public Color RegularLineColor
        {
            get { return regularLineColor; }
            set
            {
                regularLineColor = value;
            }
        }

        [Description("正常文本色"), Category("自定义")]
        public Color RegularTextColor
        {
            get { return regularTextColor; }
            set
            {
                regularTextColor = value;
            }
        }

        [Description("鼠标选中背景色"), Category("自定义")]
        public Color MouseInBaseColor
        {
            get { return mouseInBaseColor; }
            set
            {
                mouseInBaseColor = value;
            }
        }

        [Description("鼠标选中边框色"), Category("自定义")]
        public Color MouseInLineColor
        {
            get { return mouseInLineColor; }
            set
            {
                mouseInLineColor = value;
            }
        }

        [Description("鼠标选中文本色"), Category("自定义")]
        public Color MouseInTextColor
        {
            get { return mouseInTextColor; }
            set
            {
                mouseInTextColor = value;
            }
        }

        [Description("鼠标按下背景色"), Category("自定义")]
        public Color MouseDownBaseColor
        {
            get { return mouseDownBaseColor; }
            set
            {
                mouseDownBaseColor = value;
            }
        }

        [Description("鼠标按下边框色"), Category("自定义")]
        public Color MouseDownLineColor
        {
            get { return mouseDownLineColor; }
            set
            {
                mouseDownLineColor = value;
            }
        }

        [Description("鼠标按下文本色"), Category("自定义")]
        public Color MouseDownTextColor
        {
            get { return mouseDownTextColor; }
            set
            {
                mouseDownTextColor = value;
            }
        }

        [Description("正常显示图标"), Category("自定义")]
        public Image IcoRegular
        {
            get { return icoRegular; }
            set
            {
                icoRegular = value;
            }
        }

        [Description("鼠标选中图标"), Category("自定义")]
        public Image IcoIn
        {
            get { return icoIn; }
            set
            {
                icoIn = value;
            }
        }

        [Description("鼠标按下图标"), Category("自定义")]
        public Image IcoDown
        {
            get { return icoDown; }
            set
            {
                icoDown = value;
            }
        }

        [Description("图标大小"), Category("自定义")]
        public Size IcoSize
        {
            get { return icoSize; }
            set
            {
                icoSize = value;
            }
        }

        [Description("图标x方向偏移量，为正向下，为负向上"), Category("自定义")]
        public int XoffsetIco
        {
            get { return xoffsetIco; }
            set
            {
                xoffsetIco = value;
            }
        }

        [Description("图标y方向偏移量，为正向下，为负向上"), Category("自定义")]
        public int YoffsetIco
        {
            get { return yoffsetIco; }
            set
            {
                yoffsetIco = value;
            }
        }

        /// <summary>
        /// 如果按钮文本没有单独设置的话，将使用column中设置的文本
        /// </summary>
        private string m_text = string.Empty;

        [Category("自定义"), Browsable(true), Localizable(true), Description("按钮文本")]
        public string Text
        {
            get
            {
                if (string.IsNullOrEmpty(m_text))
                    m_text = (this.OwningColumn as DataGridViewButtonColumn).Text;
                return m_text;
            }
            set
            {
                m_text = value;
            }
        }

        private Size buttonSize = new Size(60, 25);

        public Size ButtonSize
        {
            get { return buttonSize; }
            set
            {
                buttonSize = value;
            }
        }

        public bool AutoSize { get; set; } = false;

        protected Rectangle m_buttonRegion = Rectangle.Empty;// 当前按钮位置大小

        protected Rectangle m_absBtnRegion = Rectangle.Empty;// 当前按钮绝对位置大小

        protected PushButtonState m_curBtnState = PushButtonState.Normal;// 当前按钮状态

        public PPDataGridView PPDataGridView
        {
            get { return this.DataGridView as PPDataGridView; }
        }

        public PPDataGridViewButtonCell()
        {
            m_curBtnState = PushButtonState.Normal;// 当前按钮状态
        }

        public override object Clone()
        {
            return base.Clone();
        }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            //graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            Rectangle rect = GetSmallRectOfRectangle(cellBounds, buttonSize, out this.m_absBtnRegion);
            DrawButton(graphics, rect, m_curBtnState);
            //ButtonRenderer.DrawButton(graphics, rect, m_curBtnState);
            //TextRenderer.DrawText(graphics, this.Text, this.PPDataGridView.CellFont, rect, this.PPDataGridView.CellForeColor);
            //base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }

        private void DrawButton(Graphics g, Rectangle rect, PushButtonState buttonstate)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            if (this.PPDataGridView.TextDrawMode == PPDataGridView.DrawMode.Clear)
            {
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            }
            Color backColor = regularBaseColor;
            Color lineColor = regularLineColor;
            Color foreColor = regularTextColor;
            Image img = icoRegular;
            if (buttonstate == PushButtonState.Hot)
            {
                backColor = mouseInBaseColor;
                lineColor = mouseInLineColor;
                foreColor = mouseInTextColor;
                img = icoIn;
            }
            else if (buttonstate == PushButtonState.Pressed)
            {
                backColor = mouseDownBaseColor;
                lineColor = mouseDownLineColor;
                foreColor = mouseDownTextColor;
                img = icoDown;
            }

            GraphicsPath path1 = CreateRound(rect, radius);
            g.FillPath(new SolidBrush(backColor), path1);
            g.DrawPath(new Pen(lineColor, lineWidth), path1);
            Size fontsize = TextRenderer.MeasureText(this.Text, this.PPDataGridView.CellFont);
            g.DrawString(this.Text, this.PPDataGridView.CellFont, new SolidBrush(foreColor), new Point(rect.X + rect.Width / 2 - fontsize.Width / 2 + 2 + xoffset, rect.Y + rect.Height / 2 - fontsize.Height / 2 + yoffset));
            if (img != null)
            {
                g.DrawImage(img, new Rectangle(new Point(rect.X + xoffsetIco, rect.Y + yoffsetIco), icoSize));
            }
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
        }

        private GraphicsPath CreateRound(Rectangle rect, int radius)
        {
            GraphicsPath roundRect = new GraphicsPath();
            int halfradius = radius % 2 == 0 ? radius / 2 : radius / 2 + 1;
            if (radius != 0)
            {
                //顶端
                //roundRect.AddLine(rect.Left + halfradius-1, rect.Top, rect.Right - halfradius, rect.Top);
                //右上角
                roundRect.AddArc(rect.Right - radius, rect.Top, radius, radius, 270f, 90f);
                //右边
                //roundRect.AddLine(rect.Right, rect.Top + halfradius, rect.Right, rect.Bottom - halfradius);
                //右下角

                roundRect.AddArc(rect.Right - radius, rect.Bottom - radius, radius, radius, 0f, 90f);
                //底边
                //roundRect.AddLine(rect.Right - halfradius, rect.Bottom, rect.Left + halfradius, rect.Bottom);
                //左下角
                roundRect.AddArc(rect.Left, rect.Bottom - radius, radius, radius, 90f, 90f);
                //左边
                //roundRect.AddLine(rect.Left, rect.Top + halfradius, rect.Left, rect.Bottom - halfradius);
                //左上角
                roundRect.AddArc(rect.Left, rect.Top, radius, radius, 180f, 90f);

                roundRect.CloseFigure();
            }
            else
            {
                //顶端
                roundRect.AddLine(rect.Left, rect.Top, rect.Right, rect.Top);
                //右边
                roundRect.AddLine(rect.Right, rect.Top, rect.Right, rect.Bottom);
                //底边
                roundRect.AddLine(rect.Right, rect.Bottom, rect.Left, rect.Bottom);
                //左边
                roundRect.AddLine(rect.Left, rect.Top, rect.Left, rect.Bottom);
            }

            return roundRect;
        }

        protected override void OnMouseMove(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsInRegion(e.Location, e.ColumnIndex, e.RowIndex))
            {
                this.m_curBtnState = PushButtonState.Hot;
                this.DataGridView.Cursor = Cursors.Hand;
            }
            else
            {
                this.m_curBtnState = PushButtonState.Normal;
                this.DataGridView.Cursor = Cursors.Default;
            }
            this.DataGridView.InvalidateCell(this);
        }

        protected override void OnMouseLeave(int rowIndex)
        {
            base.OnMouseLeave(rowIndex);
            this.m_curBtnState = PushButtonState.Normal;
            this.DataGridView.Cursor = Cursors.Default;
            this.DataGridView.InvalidateCell(this);
        }

        protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (IsInRegion(e.Location, e.ColumnIndex, e.RowIndex))
            {
                this.m_curBtnState = PushButtonState.Pressed;
            }
            else
            {
                this.m_curBtnState = PushButtonState.Normal;
            }
            this.DataGridView.InvalidateCell(this);
        }

        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
            if (this.PPDataGridView != null)
                this.PPDataGridView.OnButtonClicked(e.ColumnIndex, e.RowIndex, this.Value, e.Button, e.Clicks);
            base.OnMouseClick(e);
        }

        protected override void OnMouseDoubleClick(DataGridViewCellMouseEventArgs e)
        {
            if (this.PPDataGridView != null)
                this.PPDataGridView.OnButtonClicked(e.ColumnIndex, e.RowIndex, this.Value, e.Button, e.Clicks);
            base.OnMouseDoubleClick(e);
        }

        /// <summary>
        /// 是否在Button按钮区域
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        protected bool IsInRegion(Point p, int columnIndex, int rowIndex)
        {
            Rectangle cellBounds = DataGridView[columnIndex, rowIndex].ContentBounds;
            GetSmallRectOfRectangle(cellBounds, buttonSize, out this.m_absBtnRegion);
            return this.m_absBtnRegion.Contains(p);
        }

        private Rectangle GetSmallRectOfRectangle(Rectangle rectangle, Size smallSize, out Rectangle absRectangle)
        {
            Rectangle rect = new Rectangle();
            if (!AutoSize)
            {
                absRectangle = new Rectangle();
                absRectangle.Size = smallSize;
                absRectangle.X = (rectangle.Width - smallSize.Width) / 2;
                absRectangle.Y = (rectangle.Height - smallSize.Height) / 2;
                rect.Size = smallSize;
                rect.X = absRectangle.X + rectangle.X;
                rect.Y = absRectangle.Y + rectangle.Y;
            }
            else
            {
                absRectangle = rectangle;
                rect.X = rectangle.X + 2;
                rect.Y = rectangle.Y + 2;
                rect.Width = rectangle.Width - 6;
                rect.Height = rectangle.Height - 6;
            }

            return rect;
        }
    }

    public class PPDataGridViewButtonColumn : DataGridViewButtonColumn
    {
        public PPDataGridViewButtonColumn()
        {
            this.CellTemplate = new PPDataGridViewButtonCell();
        }

        public PPDataGridViewButtonColumn(string HeaderText)
        {
            this.CellTemplate = new PPDataGridViewButtonCell();
            this.HeaderText = HeaderText;
            this.Text = HeaderText;
        }
    }
}